#include "DndData.h"
#include "CacheEntry.h"
#include "Trait.h"
#include "Power.h"
#include "Race.h"

#include <QTextStream>

/*!
 * \class DndData
 * \brief D&D 4 specific values, enumerations and constant data.
 * \details This class encapsulates via enums and string constants
 * the core data and types needed to model character information.
 *
 * For more details read "Chapter 2: Making Characters" in the
 * Dungeons and Dragons 4th Ed Players Handbook.
 */



/*!
 * \enum DndData::Ability
 * \brief The D&D 4 base statistics.
 * \details These base stats control the characters performance
 * either directly or by contributing to other derived stats like
 * skills.
 *
 * \var DndData::Ability DndData::STRENGTH
 * Affects most attacks, and skills like Athletics.
 */
/*!
 * \var DndData::Ability DndData::CONSTITUTION
 * Affects hit points and some attacks.
 */
/*! \var DndData::Ability DndData::DEXTERITY
 * Contributes to ranged attacks, and also armor class.
 */
/*! \var DndData::Ability DndData::INTELLIGENCE
 * For knowledge based skills, and some magic attacks.
 */
/*! \var DndData::Ability DndData::WISDOM
 * For Cleric attacks and the will defence.
 */
/*! \var DndData::Ability DndData::CHARISMA
 * For Paladin attacks and some skills, such as bluff.
 */


/*!
 * String versions of the DndData::Ability enum.
 */
const char *DndData::ABILITY_NAMES[] = {
    "Strength",
    "Constitution",
    "Dexterity",
    "Intelligence",
    "Wisdom",
    "Charisma"
};

const int DndData::NUM_ABILITIES;
const int DndData::STANDARD_ARRAY[] = { 16, 14, 13, 12, 11, 10 };
const int DndData::NUM_CLASSES;
const char *DndData::CLASS_NAMES[] = {
    "Cleric",
    "Fighter",
    "Paladin",
    "Ranger",
    "Rogue",
    "Warlock",
    "Warlord",
    "Wizard"
};

/*!
 * \enum DndData::Tier
 * \brief Tiers from the D&D 4 system.
 * \details Characters start out as Heroic Tier characters,
 * and advance to Paragon and Epic Destiny, at 11th and 21st
 * level respectively.  As they do so, many standard powers
 * and benefits increment.
 * \var DndData::HEROIC the starting Tier, levels 1 thru 10
 * \var DndData::PARAGON for character levels 11 thru 20
 * \var DndData::EPIC_DESTINY for levels 21 and above.
 */

/*!
 * String equivalents of the DndData::Tier enum.
 */
const char *DndData::TIER_NAMES[] = {
        "Heroic",
        "Paragon",
        "Epic Destiny"
};

const int DndData::APTITUDE_ABILITIES[][DndData::NUM_ABILITIES] = {
    // Cleric
    { DndData::WISDOM, DndData::STRENGTH, DndData::CHARISMA,
        DndData::INTELLIGENCE, DndData::CONSTITUTION, DndData::DEXTERITY },
    // Fighter
    { DndData::STRENGTH, DndData::DEXTERITY, DndData::WISDOM,
        DndData::CONSTITUTION, DndData::CHARISMA, DndData::INTELLIGENCE },
    // Paladin
    { DndData::STRENGTH, DndData::CHARISMA, DndData::WISDOM,
        DndData::CONSTITUTION, DndData::DEXTERITY, DndData::INTELLIGENCE },
    // Ranger
    { DndData::STRENGTH, DndData::DEXTERITY, DndData::WISDOM,
        DndData::CONSTITUTION, DndData::CHARISMA, DndData::INTELLIGENCE },
    // Rogue
    { DndData::DEXTERITY, DndData::STRENGTH, DndData::CHARISMA,
        DndData::CONSTITUTION, DndData::INTELLIGENCE, DndData::WISDOM },
    // Warlock
    { DndData::CHARISMA, DndData::CONSTITUTION, DndData::INTELLIGENCE,
        DndData::WISDOM, DndData::DEXTERITY, DndData::STRENGTH },
    // Warlord
    { DndData::STRENGTH, DndData::INTELLIGENCE, DndData::CHARISMA,
        DndData::WISDOM, DndData::CONSTITUTION, DndData::DEXTERITY },
    // Wizard
    { DndData::INTELLIGENCE, DndData::WISDOM, DndData::DEXTERITY,
        DndData::CONSTITUTION, DndData::CHARISMA, DndData::STRENGTH }
};

const int DndData::CUSTOMIZED_COSTS[] = { -2, -1, 0, 1, 2, 3, 5, 7, 9, 12, 16 };

const int DndData::CUSTOMIZE_SCORES_ARRAY[] = { 8, 10, 10, 10, 10, 10 };

const int DndData::CUSTOMIZED_POINTS = 22;

const char *DndData::RACE_NAMES[] = {
    "Dragonborn",
    "Dwarf",
    "Eladrin",
    "Elf",
    "Half-elf",
    "Halfling",
    "Human",
    "Tiefling"
};

const char *DndData::SIZE_NAMES[] = {
    "Tiny",
    "Small",
    "Medium",
    "Large",
    "Huge",
    "Gargantuan"
};

const char *DndData::VISION_TYPES[] = {
        "Normal vision",
        "Low-light vision",
        "Dark vision"
};

const char *DndData::LANGUAGE_NAMES[] = {
    "Abyssal",
    "Common",
    "Deep Speech",
    "Draconic",
    "Dwarven",
    "Elven",
    "Giant",
    "Goblin",
    "Primordial",
    "Supernal",
    "Choice of any"
};

const char *DndData::SKILL_TYPES[] = {
        "Acrobatics",
        "Arcana",
        "Athletics",
        "Bluff",
        "Dungeoneering",
        "Endurance",
        "Heal",
        "History",
        "Insight",
        "Intimidate",
        "Nature",
        "Perception",
        "Religion",
        "Stealth",
        "Streetwise",
        "Thievery"
};

const char *DndData::ROLE_NAMES[] = {
        "Leader",
        "Controller",
        "Defender",
        "Striker"
};

const char *DndData::GENDER_NAMES[] = {
    "Male",
    "Female"
};

const char *DndData::ALIGNMENT_NAMES[] = {
        "Good",
        "Lawful Good",
        "Unaligned",
        "Evil",
        "Chaotic Evil"
};

const char *DndData::DEITY_NAMES[] = {
        "Avandra",
        "Bahamut",
        "Corellon",
        "Erathis",
        "Ioun",
        "Kord",
        "Melora",
        "Moradin",
        "Pelor",
        "The Raven Queen",
        "Sehanine",
};

const char *DndData::EVIL_DEITY_NAMES[] = {
        "Asmodeus",
        "Bane",
        "Gruumsh",
        "Lolth",
        "Tiamat",
        "Torog",
        "Vecna",
        "Zehir"
};

const char *DndData::ARMOUR_WEIGHT_NAMES[] = {
    "Light",
    "Heavy"
};

DndData::DndData()
{
}

DndData::~DndData()
{
}

QTextStream & operator>>(QTextStream &s, DndData::Ability &data)
{
    int result;
    s >> result;
    if (result >= DndData::NUM_ABILITIES)
        qFatal("Expecting DndData::Ability < %d, got %d",
                DndData::NUM_ABILITIES, result);
        data = DndData::Ability(result);
        return s;
}

QTextStream & operator>>(QTextStream &s, DndData::DefenceType &data)
{
    int result;
    s >> result;
    data = DndData::DefenceType(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, DndData::ClassName &data)
{
    int result;
    s >> result;
    data = DndData::ClassName(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, DndData::BodySize &data)
{
    int result;
    s >> result;
    data = DndData::BodySize(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, DndData::VisionType &data)
{
    int result;
    s >> result;
    data = DndData::VisionType(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, DndData::SkillTypes &data)
{
    int result;
    s >> result;
    data = DndData::SkillTypes(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, DndData::PartyRole &data)
{
    int result;
    s >> result;
    data = DndData::PartyRole(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, DndData::Language &data)
{
    int result;
    s >> result;
    data = DndData::Language(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, DndData::RaceName &data)
{
    int result;
    s >> result;
    data = DndData::RaceName(result);
    return s;
}

QTextStream & operator>>(QTextStream &s, DndData::Tier &data)
{
    int result;
    s >> result;
    data = DndData::Tier(result);
    return s;
}
